from rest_framework import serializers
from django.db import transaction

from goods.models import SKU, GoodsCategory, SPUSpecification, SpecificationOption, SKUSpecification
from celery_tasks.static_files.tasks import generate_static_sku_detail_html


class SkuSpecificationSerializer(serializers.ModelSerializer):
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = ('id', 'spec_id', 'option_id')


class SkuSerializer(serializers.ModelSerializer):
    spu_id = serializers.IntegerField()
    category_id = serializers.IntegerField()

    specs = SkuSpecificationSerializer(read_only=True, many=True)

    class Meta:
        model = SKU
        fields = "__all__"
        read_only_fields = ('spu', 'category')

    def create(self, validated_data):
        specs = self.context['request'].data.get('specs')

        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                sku = SKU.objects.create(**validated_data)
                for spec in specs:
                    SKUSpecification.objects.create(sku=sku, spec_id=spec['spec_id'], option_id=spec['option_id'])
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('Save failure')
            else:
                transaction.savepoint_commit(save_point)

            generate_static_sku_detail_html.delay(id=sku.id)

            return sku

    def update(self, instance, validated_data):
        specs = self.context['request'].data.get('specs')

        with transaction.atomic():
            save_point = transaction.savepoint()
            try:
                SKU.objects.get(id=instance.id).update(**validated_data)
                for spec in specs:
                    SKUSpecification.objects.filter(sku_id=instance.id).update(**spec)
            except:
                transaction.savepoint_rollback(save_point)
                raise serializers.ValidationError('Save failure')
            else:
                transaction.savepoint_commit(save_point)

        generate_static_sku_detail_html.delay(id=instance.id)

        return instance


class GoodCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = "__all__"


class SpecificationOptionsSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = "__all__"


class SPUspecsSerializer(serializers.ModelSerializer):
    options = SpecificationOptionsSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = "__all__"

